'''
Created on 17/02/2010

@author: eh01
'''
from xml.etree import ElementTree

def pre_parse_xml_to_add_namespace_data_to_elements(schema_file_fp):

####################################################################################################################
# NOTES
####################################################################################################################
#         The 'start' and 'end' events represent opening and closing element. They are accompanied by the respective 
#         Element instance.  By default, only 'end' events are generated
#         The 'start-ns' and 'end-ns' events notify about namespace declarations. They do not come with Elements.
#         Instead, the value of the 'start-ns' event is a tuple (prefix, namespaceURI) that designates the 
#         beginning of a prefix-namespace mapping. The corresponding 'end-ns' event does not have a value (None).
#         It is common practice to use a list as namespace stack and pop the last entry on the 'end-ns' event
#        
#        Example of the events
#          <root>
#            <element key='value'>text</element>
#            <element>text</element>tail
#            <empty-element xmlns="http://testns/" />
#          </root>
#        
#          >>> events = ("start", "end", "start-ns", "end-ns")
#          >>> context = etree.iterparse(StringIO(xml), events=events)
#          >>> for action, elem in context:
#          ...     if action in ('start', 'end'):
#          ...         print("%s: %s" % (action, elem.tag))
#          ...     elif action == 'start-ns':
#          ...         print("%s: %s" % (action, elem))
#          ...     else:
#          ...         print(action)
#          start: root
#          start: element
#          end: element
#          start: element
#          end: element
#          start-ns: ('', 'http://testns/')
#          start: {http://testns/}empty-element
#          end: {http://testns/}empty-element
#          end-ns
#          end: root
 
        # pre-parse wsdl and attach namespace information to each element
        root_element_tree = None
        ns_map = []       
        events = "start", "end", "start-ns", "end-ns"        
        for event, elem in ElementTree.iterparse(schema_file_fp, events):
            if event == "start-ns":
                # add the namespace mapping
                ns_map.append(elem)
            elif event == "end-ns":
                # pop up the last added namespace mapping
                ns_map.pop()
            elif event == "start":
                if root_element_tree is None:
                    root_element_tree = elem
                # add the list of namespace mappings to the element so it has access to it through ns_map variable
                elem.ns_map = dict(ns_map)
            elif event == "end":
                # do nothing
                pass
        return root_element_tree